package de.mmis.core.pojop.processor;

import java.net.URI;
import java.util.Map;

import de.mmis.core.base.ObjectDescriptor;
import de.mmis.core.base.abstracttree.Tree;
import de.mmis.core.base.abstracttree.TreeParserException;
import de.mmis.core.pojop.answer.AbstractAnswer;
import de.mmis.core.pojop.answer.AbstractAnswer.Type;
import de.mmis.core.pojop.answer.Answer;
import de.mmis.core.pojop.answer.HTTPAnswer;
import de.mmis.core.pojop.request.AbstractRequest;
import de.mmis.core.pojop.request.HTTPRequest;
import de.mmis.core.pojop.request.HTTPRequest.RequestType;
import de.mmis.core.sexpression.SExpressionParser;
import de.mmis.core.sexpression.SExpressionWriter;

public class HTTPRequestProcessorFactory extends
		AbstractRequestProcessorFactory<HTTPRequest> {

	public HTTPRequestProcessorFactory(ObjectDescriptor objectDescriptor,
			String objectID, Map<String, Object> objectProperties,
			boolean explicit) {
		super(objectDescriptor, objectID, objectProperties, explicit);
	}

	@Override
	public RequestProcessorFactory.RequestProcessor<HTTPRequest> createRequestProcessor() {
		return new HTTPRequestProcessor();
	}

	public class HTTPRequestProcessor extends AbstractRequestProcessor {
		@Override
		public Answer answerRequest(HTTPRequest request) {

			if (request.getType() == RequestType.Echo)
				return new HTTPAnswer(request.getEchoData(),
						request.getEchoContentType());

			if (request.getType() == RequestType.Error)
				return new HTTPAnswer(answerAbstractRequest(
						new AbstractRequest(request.getException()))
						.toByteArray());

			return answerURI(request.getURI());
		}

		protected HTTPAnswer answerURI(URI uri) {
			String query = uri.getQuery();
			String path = uri.getPath().substring(1);

			if (path.equalsIgnoreCase("call")) {
				try {
					return new HTTPAnswer(answerAbstractRequest(
							new AbstractRequest(
									AbstractRequest.RequestType.MethodCall,
									SExpressionParser.parseUTF8(query)))
							.toByteArray());
				} catch (TreeParserException e) {
					return new HTTPAnswer(answerAbstractRequest(
							new AbstractRequest(e)).toByteArray());
				}
			} else if (path.equalsIgnoreCase("observe")) {
				Tree filter = null;
				if (query != null)
					try {
						filter = SExpressionParser.parseUTF8(query);
					} catch (TreeParserException e) {
						return new HTTPAnswer(answerAbstractRequest(
								new AbstractRequest(e)).toByteArray());
					}

				AbstractAnswer aa = answerAbstractRequest(new AbstractRequest(
						AbstractRequest.RequestType.Observe, filter));

				if (aa.getType() == Type.OK)
					return new HTTPAnswer(new byte[0],
							HTTPAnswer.DEFAULT_CONTENT_TYPE, true);

				return new HTTPAnswer(aa.toByteArray());
			} else
				return new HTTPAnswer(answerAbstractRequest(
						new AbstractRequest(AbstractRequest.RequestType.Help,
								null)).toByteArray());
		}

		@Override
		protected void processEvent(Tree exp) {
			fireEvent(new RequestProcessorEvent(new HTTPAnswer(
					SExpressionWriter.writeSExpression(exp), false)));
		}
	}
}
